package com.example.acitividemo2.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

@Slf4j
public class BeanOverrideUtils {

    /**
     * 移除bean
     */
    public static void removeBean(BeanDefinitionRegistry beanDefinitionRegistry, List<String> overrideNames) {
        for (String overrideName : overrideNames) {
            if (overrideName == null || overrideName.trim().equals("")) {
                continue;
            }
            beanDefinitionRegistry.removeBeanDefinition(overrideName);
            log.debug("移除了bean: {}", overrideName);
        }
    }

    /**
     * 猜要重写的 bean
     */
    public static List<String> guessOverrideBean(String beanName,
                                                 BeanDefinitionRegistry beanDefinitionRegistry, int limit) {
        ConfigurableListableBeanFactory registry = (ConfigurableListableBeanFactory) beanDefinitionRegistry;
        List<String> rtn = new ArrayList<>();
        Object bean = registry.getBean(beanName);
        Class<?> beanClazz = bean.getClass();
        List<String> types = allBean(registry, supperClassAndMe(beanClazz));
        types.removeIf(s -> s.equals(beanName));
        if (limit >= types.size()) {
            limit = types.size();
        }
        for (int i = 0; i < limit; i++) {
            String type = types.get(i);
            rtn.add(type);
        }
        return rtn;
    }

    /**
     * 所有的父类以及实现的接口
     */
    public static List<Class<?>> supperClasses(Class<?> clazz) {
        ArrayList<Class<?>> classes = new ArrayList<>();
        Class<?> superclass = clazz.getSuperclass();
        if (superclass != null && !superclass.equals(Object.class)) {
            classes.add(superclass);
        }
        classes.addAll(Arrays.asList(clazz.getInterfaces()));
        return classes;
    }

    public static List<Class<?>> supperClassAndMe(Class<?> clazz) {
        List<Class<?>> classes = supperClasses(clazz);
        classes.add(clazz);
        return classes;
    }

    public static List<String> allBean(ConfigurableListableBeanFactory registry, List<Class<?>> classes) {
        List<String> rtn = new ArrayList<>();
        for (Class<?> clazz : classes) {
            String[] types = registry.getBeanNamesForType(clazz);
            for (String type : types) {
                if(!rtn.contains(type)){
                    rtn.add(type);
                }
            }
        }
        return rtn;
    }
}
